package com.allesblinkt.mucom.common;

import java.util.Vector;


import processing.core.PApplet;
import processing.core.PConstants;
import processing.core.PFont;
import processing.core.PImage;
import mathematik.Vector2f;
import traer.physics.Particle;
import traer.physics.ParticleSystem;

public class StatusRepresentation {

	private PApplet app;
	private ParticleSystem physics;

	private Vector<ClientParticle> clients;

	private Particle centerParticle;

	private PImage activeClientImage;
	private PImage clientImage;
	private PImage fileImage;


	private PFont labelFont;
	private PImage labelImage;
	private int localMouseX = 0;
	private int localMouseY = 0;
	private String activeClientHash = "";


	public final static float EDGE_LENGTH = 30;
	public final static float EDGE_STRENGTH = 0.8f;
	public final static float SPACER_STRENGTH = 2000;
	
	public final static float FILE_RADIUS = 24;

	public StatusRepresentation(PApplet theApp){
		app = theApp;

		clients = new Vector<ClientParticle>();

		physics = new ParticleSystem( 0,  0.25f );

		activeClientImage 	= app.loadImage("ClientRing_active.png");

		clientImage 	= app.loadImage("ClientRing.png");
		fileImage 	= app.loadImage("DataRing.png");
		
		labelImage = app.loadImage("label.png");
		labelFont = app.loadFont("MarkeEigenbauNormal-8.vlw");

		centerParticle = physics.makeParticle(1, 50,100, 0);		
		centerParticle.makeFixed();


	}

	public void draw(){
		physics.tick( 1.0f ); 


		app.imageMode(PConstants.CENTER);


		app.stroke(100);

		/* Draw connections */
		for(ClientParticle client: clients){

			app.line(centerParticle.position().x(),centerParticle.position().y(),client.particle.position().x(),client.particle.position().y() );

			for(FileParticle file: client.files){
				if(file.particle != null) app.line(client.particle.position().x(),client.particle.position().y(),file.particle.position().x(),file.particle.position().y() );
			}
		}

		/* Draw blobs */
		for(ClientParticle client: clients){

			if(client.clientHash.equals(activeClientHash )){
				app.image(activeClientImage, client.particle.position().x(), client.particle.position().y(), 24, 24);

			} else {
				app.image(clientImage, client.particle.position().x(), client.particle.position().y(), 24, 24);

			}
			
			for(FileParticle file: client.files){
				if(file.particle != null) app.image(fileImage, file.particle.position().x(), file.particle.position().y(), 24, 24);

			}
		}

		
		FileParticle activeFileParticle = getFileParticleUnderMouse();
		
		
		if(activeFileParticle != null){
			app.imageMode(PConstants.CORNER);
			

			
			app.translate(activeFileParticle.particle.position().x(),activeFileParticle.particle.position().y() );
				
				/* Draw label */
				app.image(labelImage,10,-14);
				app.textFont(labelFont);
				  
				  
				  String s = activeFileParticle.contentReference.getLocalName();
				  app.fill(71, 71, 71);
				  app.text(s, 30, 8-11-1, 95, 12);



			

		
		}
	


	}

	
	public void mouseAt(int mouseX, int mouseY){
		localMouseX = mouseX;
		localMouseY = mouseY;
	}
	
	public ContentItem getContentItemUnderMouse(){
		FileParticle fileParticle  = getFileParticleUnderMouse();
		
		if(fileParticle != null) return fileParticle.contentReference;
		return null;
	}
	
	private FileParticle getFileParticleUnderMouse() {
		for(ClientParticle client:clients){
			for(FileParticle file:client.files){
				if(file.particle != null){
					Particle particle = file.particle;
					
					if (localMouseX < particle.position().x() + FILE_RADIUS
							&& localMouseX > particle.position().x()
									- FILE_RADIUS
							&& localMouseY < particle.position().y()
									+ FILE_RADIUS
							&& localMouseY > particle.position().y()
									- FILE_RADIUS) {
						
						return file;

					}
				}
			}
		}
		return null;
	}

	private void addForces( Particle w, Particle r )
	{
		for ( int i = 0; i < physics.numberOfParticles(); ++i )
		{
			Particle q = physics.getParticle( i );
			if ( w != q && w != r )
				physics.makeAttraction( w, q, -SPACER_STRENGTH, 10 );
		}
	}

	public void reset(){

		clients.clear();
		physics.clear();
	}

	public void addClient(ClientItem theClientItem) { 

		Particle w = physics.makeParticle();

		ClientParticle newClient = new ClientParticle(w);

		if(theClientItem != null) newClient.clientHash = theClientItem.getHash();


		for(ContentItem contentItem:theClientItem.getContentItems()){
			FileParticle newFile = new FileParticle(null);
			newFile.contentReference = contentItem;
			newClient.files.add(newFile);
		}




		clients.add(newClient);

		addForces( w, centerParticle );
		makeSpring( w, centerParticle );

		w.moveTo( centerParticle.position().x() + app.random( -1, 1 ), centerParticle.position().y() + app.random( -1, 1 ), 0 );
	}

	
	public void setActiveClientHash(String theHash){
		activeClientHash = theHash;
	}
	


	
	public void addContentItem(ClientItem theClientItem, ContentItem theContentItem){
		for(ClientParticle client:clients){

			
			if(client.clientHash.equals(theClientItem.getHash() )){
				
					
						FileParticle newFile = new FileParticle(null);
						newFile.contentReference = theContentItem;
						client.files.add(newFile);
						
						
						Particle w = physics.makeParticle();
						newFile.particle = w;


						addForces( w, client.particle );
						makeSpring( w, client.particle );

						w.moveTo( client.particle.position().x() + app.random( -1, 1 ), client.particle.position().y() + app.random( -1, 1 ), 0 );

				
			}
		



		}

	}
	
	public void removeContentItem(ContentItem theContentItem){
		for(ClientParticle client:clients){

			Vector<FileParticle> purgeItems = new Vector<FileParticle>();
			
			for(FileParticle file:client.files){
				
				if(file.contentReference.getHashId() == theContentItem.getHashId()){
					if(file.particle != null) file.particle.kill();
					
					purgeItems.add(file);
				}

			}

			client.files.removeAll(purgeItems);



		}

	}
	
	
	
	public void hideFileParticles() {
		for(ClientParticle client:clients){
			for(FileParticle file:client.files){
				if(file.particle != null)  file.particle.kill();
				file.particle = null;
			}
		}



	}

	



	public void showFileParticles() {


		
		
		for(ClientParticle client:clients){
			for(FileParticle file:client.files){



				Particle w = physics.makeParticle();
				file.particle = w;


				addForces( w, client.particle );
				makeSpring( w, client.particle );

				w.moveTo( client.particle.position().x() + app.random( -1, 1 ), client.particle.position().y() + app.random( -1, 1 ), 0 );
			}
		}



	}

	

	
	private void makeSpring( Particle a, Particle b )
	{
		physics.makeSpring( a, b, EDGE_STRENGTH, EDGE_STRENGTH, EDGE_LENGTH );
	}

	public void moveTo(Vector2f thePosition){
		centerParticle.moveTo(thePosition.x, thePosition.y, 0);
	}


	private class ClientParticle {

		public Vector<FileParticle> files;
		public Particle particle;

		public String clientHash;

		public ClientParticle(Particle theParticle) {
			files = new Vector<FileParticle>();

			particle = theParticle;
		}

	}

	private class FileParticle {

		public Particle particle;
		public ContentItem contentReference;

		public FileParticle(Particle theParticle) {

			particle = theParticle;
		}

	}





}
